package core

import (
	"context"
	"encoding/json"
	"ez/apps/core/auto/mc"
	"gitee.com/dreamwood/ez-go/db/mgo"
	"gitee.com/dreamwood/ez-go/ez"
	"gitee.com/dreamwood/ez-go/ss"
	"time"
)

type Api struct {
	mgo.BaseDoc   `bson:"-" json:"-"`
	Id            int64      `json:"id" bson:"id,omitempty"`
	Route         string     `json:"route" bson:"route"`                 //路由
	Name          string     `json:"name" bson:"name"`                   //名称
	App           string     `json:"app" bson:"app"`                     //应用
	IsPublic      bool       `json:"isPublic" bson:"isPublic"`           //是否公开
	Sort          int64      `json:"sort" bson:"sort"`                   //排序
	L             int64      `json:"l" bson:"l"`                         //L
	R             int64      `json:"r" bson:"r"`                         //R
	Level         int64      `json:"level" bson:"level"`                 //Level
	Link          string     `json:"link" bson:"link"`                   //link
	Parent        *Api       `json:"parent" bson:"parent"`               //父级菜单
	ParentId      int64      `json:"parentId" bson:"parentId"`           //父级菜单
	Children      []*Api     `json:"children" bson:"children"`           //子菜单
	RolesAllow    []*Role    `json:"rolesAllow" bson:"rolesAllow"`       //允许角色
	RolesAllowIds []int64    `json:"rolesAllowIds" bson:"rolesAllowIds"` //允许角色
	RolesDeny     []*Role    `json:"rolesDeny" bson:"rolesDeny"`         //允许角色
	RolesDenyIds  []int64    `json:"rolesDenyIds" bson:"rolesDenyIds"`   //允许角色
	CreateAt      time.Time  `json:"createAt" bson:"createAt"`
	UpdateAt      time.Time  `json:"updateAt" bson:"updateAt"`
	DeleteAt      *time.Time `json:"deleteAt" bson:"deleteAt"`
}

func (this *Api) DocName() string { return "Api" }
func (this *Api) GetId() int64    { return this.Id }
func (this *Api) SetId(id int64)  { this.Id = id }
func (this *Api) Create() error {
	return this.GetFactory().Create(this)
}
func (this *Api) Replace() error {
	return this.GetFactory().Replace(this)
}
func (this *Api) Save() error {
	if this.Id == 0 {
		this.CreateAt = time.Now()
		this.UpdateAt = time.Now()
		return this.GetFactory().Create(this)
	} else {
		this.UpdateAt = time.Now()
		return this.GetFactory().Replace(this)
	}
}

// 伪删除
func (this *Api) Delete() error {
	return this.GetFactory().Delete(this)
}
func (this *Api) UnDelete() error {
	return this.GetFactory().UnDelete(this)
}

// 真删除
func (this *Api) Destroy() error {
	return this.GetFactory().Destroy(this)
}
func (this *Api) ToString() string {
	return string(this.ToBytes())
}
func (this *Api) ToBytes() []byte {
	data, e := json.Marshal(this)
	ez.Try(e)
	return data
}
func (this *Api) Serialize() []byte {
	data, e := json.Marshal(this)
	ez.Try(e)
	return data
}
func (this *Api) UnSerialize(data []byte) []byte {
	ez.Try(json.Unmarshal(data, this))
	return data
}
func (this *Api) LoadParent() {
	if this.ParentId == 0 {
		return
	}
	this.Parent, _ = NewApiCrud().FindId(this.ParentId)
}
func (this *Api) LoadChildren() {
	children, _ := NewApiCrud().FindBy(ss.M{"parentId": this.Id}, []string{"id"}, 0, 0)
	this.Children = children
}
func (this *Api) LoadRolesAllow() {
	if this.RolesAllow == nil {
		this.RolesAllow = make([]*Role, 0)
	}
	if this.RolesAllowIds == nil {
		this.RolesAllowIds = make([]int64, 0)
	}
	if len(this.RolesAllowIds) > 0 {
		this.RolesAllow = make([]*Role, 0)
		for _, v := range this.RolesAllowIds {
			find, e := NewRoleCrud().FindId(v)
			if e == nil {
				this.RolesAllow = append(this.RolesAllow, find)
			}
		}
	}
}
func (this *Api) LoadRolesDeny() {
	if this.RolesDeny == nil {
		this.RolesDeny = make([]*Role, 0)
	}
	if this.RolesDenyIds == nil {
		this.RolesDenyIds = make([]int64, 0)
	}
	if len(this.RolesDenyIds) > 0 {
		this.RolesDeny = make([]*Role, 0)
		for _, v := range this.RolesDenyIds {
			find, e := NewRoleCrud().FindId(v)
			if e == nil {
				this.RolesDeny = append(this.RolesDeny, find)
			}
		}
	}
}
func (this *Api) ClearRelationsBeforeSave() mgo.Doc {
	this.Parent = nil
	this.Children = nil
	this.RolesAllow = nil
	this.RolesDeny = nil
	return this
}
func neverUsed_Api() {
	//导入ss包
	a := ss.M{}
	ez.Debug(a)
}

type ApiAccessControl struct {
	Access  bool
	Message string
	Action  string //控制器Action,小写开头，如c,u,r,d
	Model   *Api
	Session *ez.Session
}

func NewApiAccessControl(model *Api, action string, session *ez.Session) *ApiAccessControl {
	ctrl := &ApiAccessControl{
		Access:  true,
		Model:   model,
		Action:  action,
		Session: session,
	}
	ez.DispatchToMany(mc.ApiAccessControlEvent, ctrl, context.TODO())
	return ctrl
}
